package com.pureut.order.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pureut.common.core.exception.GlobalException;
import com.pureut.common.core.utils.StringUtils;
import com.pureut.common.core.utils.bean.BeanUtils;
import com.pureut.common.core.web.domain.AjaxResult;
import com.pureut.common.datascope.annotation.DataScope;
import com.pureut.common.security.utils.DictUtils;
import com.pureut.common.security.utils.SecurityUtils;
import com.pureut.order.domain.CustomerComplaintsManagement;
import com.pureut.order.domain.CustomerManagement;
import com.pureut.order.dto.CustomerManagementDto;
import com.pureut.order.dto.CustomerManagementMqDto;
import com.pureut.order.export.CustomerManagementExport;
import com.pureut.order.export.CustomerManagementimportExport;
import com.pureut.order.mapper.CustomerComplaintsManagementMapper;
import com.pureut.order.mapper.CustomerManagementMapper;
import com.pureut.order.service.CustomerManagementService;
import com.pureut.order.util.VariousMqUtil;
import com.pureut.order.vo.CustomerManagementVo;
import com.pureut.order.vo.OrderReviewVo;
import com.pureut.system.api.FeignService;
import com.pureut.system.api.OrderFeignService;
import com.pureut.system.api.domain.SysDictData;
import com.pureut.system.api.domain.SysUser;
import com.pureut.system.api.vo.SysAuditHistoryVo;
import com.pureut.system.api.vo.SysWorkbenchAuditAgentVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CustomerManagementServiceImpl extends ServiceImpl<CustomerManagementMapper, CustomerManagement> implements CustomerManagementService {


    @Resource
    FeignService feignService;

    @Resource
    OrderFeignService orderFeignService;

    @Resource
    CustomerManagementMapper customerManagementMapper;

    @Resource
    CustomerComplaintsManagementMapper customerComplaintsManagementMapper;


    /**
     * 客户列表
     *
     * @param customerManagementVo
     * @return
     */
    @Override
    @DataScope(deptAlias = "customer_management")
    public List<CustomerManagementDto> getList(CustomerManagementVo customerManagementVo) {
        List<CustomerManagementDto> converterList = customerManagementMapper.getCoustomerList(customerManagementVo);
        //获取客户状态缓存字典数据
        List<SysDictData> array = DictUtils.getDictCache("customer_status");
        Map<String, String> actualMap = array.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取客户所属机构缓存字典数据
        List<SysDictData> organizationArray = DictUtils.getDictCache("customer_affiliated_organization");
        Map<String, String> organizationMap = organizationArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //获取客户等级缓存字典数据
        List<SysDictData> levelArray = DictUtils.getDictCache("customer_level");
        Map<String, String> levelMap = levelArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        for (CustomerManagementDto entity : converterList) {
            //获取客户状态缓存字典数据
            entity.setAuditStatusDict(actualMap.get(entity.getAuditStatus()));
            //获取客户所属机构缓存字典数据
//            entity.setAffiliatedOrganizationDict(organizationMap.get(entity.getAffiliatedOrganization()));
            //获取客户等级缓存字典数据
            entity.setCustomerLevelDict(levelMap.get(entity.getCustomerLevel()));
            //归属人
            entity.setAscriptionBy(feignService.getUserName(Long.parseLong(entity.getAscriptionBy())));
        }
        return converterList;
    }

    /**
     * 客户新增
     *
     * @param customerManagementVo
     * @return
     */
    @Override
    public boolean addConverter(CustomerManagementVo customerManagementVo) throws Exception {
        //判断简称是否存在
        CustomerManagement customerManagementOne = getOne(new QueryWrapper<CustomerManagement>().lambda().eq(CustomerManagement::getCustomerAbbreviation, customerManagementVo.getCustomerAbbreviation()));
        if (customerManagementOne != null) {
            throw new GlobalException("该客户简称已经存在");
        }
        CustomerManagement customerManagement = new CustomerManagement();
        customerManagement.setDeptId(SecurityUtils.getDeptId());
        customerManagement.setCustomerName(customerManagementVo.getCustomerName());
        customerManagement.setCustomerAbbreviation(customerManagementVo.getCustomerAbbreviation());
        String authorityCoding = feignService.getAuthorityCoding("order:customer:list");
        if (authorityCoding == null) {
            throw new GlobalException("未进行单据配置,单据编码生成失败");
        }
        customerManagement.setCustomerNum(authorityCoding);
        customerManagement.setCustomerLevel(Integer.parseInt(customerManagementVo.getCustomerLevel()));
        customerManagement.setCreateBy(SecurityUtils.getUsername());
        customerManagement.setContactsBy(customerManagementVo.getContactsBy());
        customerManagement.setContactsInformation(customerManagementVo.getContactsInformation());
        customerManagement.setCustomerAddress(customerManagementVo.getCustomerAddress());
        customerManagement.setInvoicingInformation(customerManagementVo.getInvoicingInformation());
        customerManagement.setBusinessLicense(customerManagementVo.getBusinessLicense());
        customerManagement.setAuditStatus(1);
        customerManagement.setCreateTime(new Date());
        customerManagement.setRemark(customerManagementVo.getRemark());
        if (customerManagementVo.getAscriptionBy() != 0) {
            customerManagement.setAscriptionBy(customerManagementVo.getAscriptionBy());
        }
        //mq发送消息
        CustomerManagementMqDto customerManagementMqDto = new CustomerManagementMqDto();
        BeanUtils.copyProperties(customerManagement, customerManagementMqDto);
        VariousMqUtil.customerManagementMqSend(customerManagementMqDto);
        return save(customerManagement);
    }

    /**
     * 冻结客户
     *
     * @param id
     * @return
     */
    @Override
    public boolean frozenSupplier(Long id) {
        CustomerManagement customerManagement = getById(id);
        if (customerManagement.getAuditStatus() == 4) {
            customerManagement.setAuditStatus(5);
            return updateById(customerManagement);
        } else {
            throw new GlobalException("只能冻结启用的客户");
        }

    }

    /**
     * 客户解冻
     *
     * @param id
     * @return
     */
    @Override
    public boolean thawSupplier(Long id) {
        CustomerManagement customerManagement = getById(id);
        if (customerManagement.getAuditStatus() == 5) {
            customerManagement.setAuditStatus(4);
            return updateById(customerManagement);
        } else {
            throw new GlobalException("只能解冻已冻结的数据");
        }

    }

    /**
     * 撤销审核
     *
     * @param id
     * @return
     */
    @Override
    public boolean revokeApproval(Long id) {
        CustomerManagement customerManagement = getById(id);
        if (customerManagement.getAuditStatus() == 2) {
            customerManagement.setAuditStatus(1);

            feignService.deleteDoc(customerManagement.getCustomerNum(),"客户管理");

            return updateById(customerManagement);
        } else {
            throw new GlobalException("只能撤销待审核的数据");
        }

    }

    /**
     * 客户信息导出
     *
     * @param customerManagementVo
     * @return
     */
    @Override
    public List<CustomerManagementExport> getInfoExport(CustomerManagementVo customerManagementVo) {
        List<CustomerManagementExport> exportList;
        //获取客户状态缓存字典数据
        List<SysDictData> array = DictUtils.getDictCache("customer_status");
        Map<String, String> actualMap = array.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        //获取客户等级缓存字典数据
        List<SysDictData> levelArray = DictUtils.getDictCache("customer_level");
        Map<String, String> levelMap = levelArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        if (customerManagementVo.getIdStr() == null) {
            exportList = customerManagementMapper.getExportList(customerManagementVo);
        } else {
            List<String> idList = Arrays.asList(customerManagementVo.getIdStr().split(","));
            exportList = customerManagementMapper.getDataByIdStr(idList);
        }
        for (CustomerManagementExport entity : exportList) {
            //状态
            entity.setAuditStatus(actualMap.get(entity.getAuditStatus()));
            //等级
            entity.setCustomerLevel(levelMap.get(entity.getCustomerLevel()));
            //归属人
            if (entity.getAscriptionBy() != null) {
                String ascriptionBy = entity.getAscriptionBy();
                entity.setAscriptionBy(feignService.getUserName(Long.valueOf(ascriptionBy)));
            }
        }
        return exportList;
    }


    /**
     * 导入客户
     *
     * @param coCustomer
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importMouldData(List<CustomerManagementimportExport> coCustomer) {
        if (StringUtils.isNull(coCustomer) || coCustomer.size() == 0) {
            throw new GlobalException("导入客户信息不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        //获取客户等级缓存字典数据
        List<SysDictData> levelArray = DictUtils.getDictCache("customer_level");
        Map<String, String> levelMap = levelArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        for (CustomerManagementimportExport mouldModelExport : coCustomer) {
            CustomerManagement customerManagement = new CustomerManagement();
            try {
                //赋值
                customerManagement.setCustomerName(mouldModelExport.getCustomerName());

                //校验加工商简称是否为空
                boolean matches = mouldModelExport.getCustomerAbbreviation().matches("[A-Z]{0,4}");
                if (!matches){
                    throw new GlobalException("加工商简称必须为4位大写字母");
                }

                //判断简称是否存在
                CustomerManagement customerManagementOne = getOne(new QueryWrapper<CustomerManagement>().lambda().eq(CustomerManagement::getCustomerAbbreviation, mouldModelExport.getCustomerAbbreviation()));
                if (customerManagementOne != null) {
                    throw new GlobalException("该客户简称已经存在");
                }
                customerManagement.setCustomerAbbreviation(mouldModelExport.getCustomerAbbreviation());
                String authorityCoding = feignService.getAuthorityCoding("order:customer:list");
                if (authorityCoding == null) {
                    throw new GlobalException("未进行单据配置,单据编码生成失败");
                }
                customerManagement.setCustomerNum(authorityCoding);
                //客户等级
                for (Map.Entry<String, String> entry : levelMap.entrySet()) {
                    if (entry.getValue().equals(mouldModelExport.getCustomerLevel())) {
                        customerManagement.setCustomerLevel(Integer.parseInt(entry.getKey()));
                        break;
                    }
                }
                //联系人
                customerManagement.setContactsBy(mouldModelExport.getContactsBy());
                customerManagement.setContactsInformation(mouldModelExport.getContactsInformation());
                //判断归属人是否存在
                String userName = mouldModelExport.getAscriptionBy();
                if (userName != null) {
                    AjaxResult byUserName = feignService.getByUserName(userName);
                    SysUser data = JSON.parseObject(JSON.toJSONString(byUserName.get("data")), SysUser.class);
                    if (data.getUserId() == null) {
                        throw new GlobalException("该归属人不存在");
                    } else {
                        customerManagement.setAscriptionBy(data.getUserId());
                    }
                }

                customerManagement.setCreateBy(SecurityUtils.getUsername());
                customerManagement.setAuditStatus(1);
                customerManagement.setCustomerAddress(mouldModelExport.getCustomerAddress());
                customerManagement.setCreateTime(new Date());
                customerManagement.setRemark(mouldModelExport.getRemark());
                customerManagement.setDeptId(SecurityUtils.getDeptId());
                save(customerManagement);

                //mq发送消息
                CustomerManagementMqDto customerManagementMqDto = new CustomerManagementMqDto();
                BeanUtils.copyProperties(customerManagement, customerManagementMqDto);
                VariousMqUtil.customerManagementMqSend(customerManagementMqDto);

                successNum++;
                successMsg.append(successNum).append("、客户信息 ").append(mouldModelExport.getCustomerName()).append(" 导入成功");

            } catch (Exception e) {
                failureNum++;
                String msg = failureNum + "、客户 " + mouldModelExport.getCustomerName() + " 导入失败：";
                failureMsg.append(msg).append(e.getMessage());
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new GlobalException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }

        return successMsg.toString();
    }

    /**
     * 查看客户信息
     *
     * @param id
     * @return
     */
    @Override
    public CustomerManagementDto getCustomerById(Long id) {
        CustomerManagementDto customerManagementDto = new CustomerManagementDto();
        CustomerManagement customerManagement = getById(id);
        BeanUtils.copyProperties(customerManagement, customerManagementDto);
        //获取客户所属机构缓存字典数据
        List<SysDictData> organizationArray = DictUtils.getDictCache("customer_affiliated_organization");
        Map<String, String> organizationMap = organizationArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
//        customerManagementDto.setAffiliatedOrganization(String.valueOf(customerManagement.getAffiliatedOrganization()));
//        customerManagementDto.setAffiliatedOrganizationDict(organizationMap.get(String.valueOf(customerManagement.getAffiliatedOrganization())));

        //获取客户等级缓存字典数据
        List<SysDictData> levelArray = DictUtils.getDictCache("customer_level");
        Map<String, String> levelMap = levelArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        customerManagementDto.setCustomerLevel(String.valueOf(customerManagement.getCustomerLevel()));
        customerManagementDto.setCustomerLevelDict(levelMap.get(String.valueOf(customerManagement.getCustomerLevel())));
        //归属人
        if (customerManagement.getAscriptionBy() != 0) {
            Long userId = customerManagement.getAscriptionBy();
            String userName = feignService.getUserName(userId);
            customerManagementDto.setAscriptionBy(String.valueOf(userId));
//            customerManagementDto.setAscriptionByDict(userName);
        }
        return customerManagementDto;
    }

    /**
     * 删除客户
     *
     * @param ids
     * @return
     */
    @Override
    public boolean getDeleteByIds(String ids) throws Exception {
        if (ids != null) {
            List<CustomerManagement> customerManagementsList = new ArrayList<>();

            List<String> stringIds = Arrays.asList(ids.split(","));
            //获取客户列表
            List<CustomerManagement> customerManagements = customerManagementMapper.selectBatchIds(stringIds);

            for (CustomerManagement entity : customerManagements) {

                List<CustomerComplaintsManagement> customerComplaintsManagements = customerComplaintsManagementMapper.selectList(new QueryWrapper<CustomerComplaintsManagement>().lambda().eq(CustomerComplaintsManagement::getCustomerId, entity.getId()));
                //如果没有关联数据，并且状态为已冻结，或者状态为待提交、未通过就放入删除列表
                boolean delData = 6 == entity.getAuditStatus() && customerComplaintsManagements.size() == 0;
                if (delData || entity.getAuditStatus() == 1 || entity.getAuditStatus() == 5) {
                    customerManagementsList.add(entity);

                    feignService.deleteDoc(entity.getCustomerNum(),"客户管理");
                } else {
                    throw new GlobalException("只能删除状态为待提交、未通过或者已冻结并且无关联的客户");
                }
            }

            if (customerManagementsList.size() > 0) {
                StringBuilder stringBuilder = new StringBuilder();
                for (CustomerManagement entity : customerManagementsList) {
                    stringBuilder.append(entity.getCustomerNum()).append(",");
                }
                StringBuilder stringBuilder1 = stringBuilder.deleteCharAt(stringBuilder.length() - 1);
                //mq同步删除客户
                CustomerManagementMqDto customerManagementMqDto = new CustomerManagementMqDto();
                customerManagementMqDto.setCustomerDeleteMark(13);
                customerManagementMqDto.setCustomerNum(stringBuilder1.toString());
                VariousMqUtil.customerManagementMqSendDelete(customerManagementMqDto);




                return removeByIds(customerManagementsList);
            } else {
                throw new SQLException("只能删除状态为待提交、未通过或者已冻结并且无关联的客户");
            }
        } else {
            throw new SQLException("至少勾选一条数据");
        }
    }

    /**
     * 提交审核
     *
     * @param id
     * @return
     */
    @Override
    public boolean reivewSubmit(Long id) {
        CustomerManagement customerManagement = getById(id);
        if (customerManagement.getAuditStatus() == 1) {
            customerManagement.setAuditStatus(2);

            SysWorkbenchAuditAgentVo sysWorkbenchAuditAgentVo = new SysWorkbenchAuditAgentVo();
            sysWorkbenchAuditAgentVo.setDocConfig("order:sale:customer:review");
            sysWorkbenchAuditAgentVo.setReceiptName("客户管理");
            sysWorkbenchAuditAgentVo.setReceiptNumber(customerManagement.getCustomerNum());//
            sysWorkbenchAuditAgentVo.setStatus(1);//待审核
            sysWorkbenchAuditAgentVo.setReceiptContent("有单据待审核,请及时审核");

            feignService.insertAuditAgent(sysWorkbenchAuditAgentVo);

            return updateById(customerManagement);
        } else {
            throw new GlobalException("只能提交待审核的数据");
        }

    }


    /**
     * 修改客户
     *
     * @param customerManagementVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCustomerById(CustomerManagementVo customerManagementVo) throws Exception {
        CustomerManagement customerManagement = getById(customerManagementVo.getId());
        if (customerManagement.getAuditStatus() == 1 || customerManagement.getAuditStatus() == 6) {
            List<CustomerManagement> list = list();
            List<CustomerManagement> collect = list.stream().filter(entity -> entity.getId() != customerManagementVo.getId()).collect(Collectors.toList());
            for (CustomerManagement entity : collect) {
                if (entity.getCustomerAbbreviation().equals(customerManagementVo.getCustomerAbbreviation())) {
                    throw new GlobalException("该客户简称已经存在");
                }
            }
            BeanUtils.copyProperties(customerManagementVo, customerManagement);
            customerManagement.setCustomerLevel(Integer.parseInt(customerManagementVo.getCustomerLevel()));
            customerManagement.setAscriptionBy(customerManagementVo.getAscriptionBy());

            if (customerManagement.getAuditStatus() == 6) {
                //调用审核
                SysAuditHistoryVo sysAuditHistoryVo = new SysAuditHistoryVo();
                String perms = "order:sale:customer:review";
                String auditDoc = customerManagement.getCustomerNum();
                sysAuditHistoryVo.setAuditDoc(auditDoc);
                sysAuditHistoryVo.setPerms(perms);
                AjaxResult history = feignService.editHistory(sysAuditHistoryVo);
                String data = JSON.parseObject(JSON.toJSONString(history.get("msg")), String.class);
                if ("操作成功".equals(data)) {
                    customerManagement.setAuditStatus(1);
                    //mq发送消息
                    CustomerManagementMqDto customerManagementMqDto = new CustomerManagementMqDto();
                    BeanUtils.copyProperties(customerManagement, customerManagementMqDto);
                    VariousMqUtil.customerManagementMqSend(customerManagementMqDto);

                    //修改审核代办状态为已处理
                    feignService.updateStatus(3,customerManagement.getCustomerNum(),"客户管理");//

                    return updateById(customerManagement);
                } else {
                    return false;
                }
            }
            //mq发送消息
            CustomerManagementMqDto customerManagementMqDto = new CustomerManagementMqDto();
            BeanUtils.copyProperties(customerManagement, customerManagementMqDto);
            VariousMqUtil.customerManagementMqSend(customerManagementMqDto);
            return updateById(customerManagement);
        } else {
            throw new GlobalException("只能修改待提交和未通过的数据");
        }

    }

    /**
     * 客户审核
     *
     * @param orderReviewVo
     * @return
     */
    @Override
    public boolean customerReview(OrderReviewVo orderReviewVo) {
        CustomerManagement customerManagement = getById(orderReviewVo.getId());
        if (customerManagement.getAuditStatus() == 2 || customerManagement.getAuditStatus() == 3) {
            String perms = "order:sale:customer:review";
            int isAdopt = orderReviewVo.getIsAdopt();
            String auditDoc = customerManagement.getCustomerNum();
            String auditRemarks = orderReviewVo.getReviewComments();
            Long userId = SecurityUtils.getUserId();
            AjaxResult sequence = feignService.getSequenceTwo(perms, 2, isAdopt, auditRemarks, auditDoc, userId);
            Integer data = JSON.parseObject(JSON.toJSONString(sequence.get("data")), Integer.class);
            if (data == null) {
                throw new GlobalException("未对该审核进行配置");
            }
            //1:通过，2：审核中，3：没权限 4:该人已经审核过
            if (orderReviewVo.getIsAdopt() == 1) {
                if (data == 1) {
                    customerManagement.setAuditStatus(4);

                    feignService.updateStatus(3,customerManagement.getCustomerNum(),"客户管理");

                    return updateById(customerManagement);
                } else if (data == 2) {
                    customerManagement.setAuditStatus(3);
                    return updateById(customerManagement);
                } else if (data == 3) {
                    throw new GlobalException("没有审核权限");
                } else {
                    throw new GlobalException("该用户已经审核过");
                }
            } else {
                if (data == 1 || data == 2) {
                    customerManagement.setAuditStatus(6);

                    SysWorkbenchAuditAgentVo sysWorkbenchAuditAgentVo = new SysWorkbenchAuditAgentVo();
                    sysWorkbenchAuditAgentVo.setDocConfig("order:sale:customer:review");
                    sysWorkbenchAuditAgentVo.setReceiptName("客户管理");
                    sysWorkbenchAuditAgentVo.setReceiptNumber(customerManagement.getCustomerNum());//
                    sysWorkbenchAuditAgentVo.setStatus(2);//待处理

                    sysWorkbenchAuditAgentVo.setPassFlag("1");
                    sysWorkbenchAuditAgentVo.setCreateName(customerManagement.getCreateBy());

                    sysWorkbenchAuditAgentVo.setReceiptContent("有单据未通过,请及时查看");

                    feignService.insertAuditAgent(sysWorkbenchAuditAgentVo);
                    return updateById(customerManagement);
                } else if (data == 3) {
                    throw new GlobalException("没有审核权限");
                } else {
                    throw new GlobalException("该用户已经审核过");
                }
            }
        } else {
            throw new GlobalException("只能对待审核和审核中的数据进行处理");
        }
    }

    /**
     * 通过客户名称获取客户id
     *
     * @param customerName
     * @return
     */
    @Override
    public CustomerManagement getCustomerId(String customerName) {
        return customerManagementMapper.getCustomerId(customerName);
    }
}
